home *** CD-ROM | disk | FTP | other *** search
- /***** BEGIN LICENSE BLOCK *****
-
- FlashGot - a Firefox extension for external download managers integration
- Copyright (C) 2004-2009 Giorgio Maone - g.maone@informaction.com
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- ***** END LICENSE BLOCK *****/
-
- function HttpInterceptor() {
- CC["@mozilla.org/uriloader;1"].getService(
- CI.nsIURILoader).registerContentListener(this);
- }
-
- HttpInterceptor.prototype = {
-
- autoStart: false,
- interceptAll: true,
- bypassAutoStart: false,
- forceAutoStart: false,
-
- lastPost: null, // last uploadChannel
-
- QueryInterface: xpcom_generateQI([
- CI.nsIURIContentListener,
- CI.nsIObserver,
- CI.nsISupportsWeakReference,
- CI.nsISupports
- ]),
-
-
- setup: function() { // profile initialization
- this.autoStart = fg.getPref("autoStart", false);
- this.interceptAll = fg.getPref("interceptAll", true);
- },
-
- dispose: function() {
- CC["@mozilla.org/uriloader;1"].getService(
- CI.nsIURILoader).unRegisterContentListener(this);
- },
-
- log: function(msg) {
- fg.log(msg);
- },
-
- _shouldIntercept: function(contentType) {
- // dump("FG: _shouldIntercept("+contentType+")\n");
- if (this.bypassAutoStart) return false;
-
- if (!(fg.DMS && fg.DMS.found)) return false;
- if (this.forceAutoStart) return true;
-
- if (!this.autoStart) return false;
-
- if (this.interceptAll &&
- !/\bxpinstall|text|xml|vnd\.mozilla|multipart\/x-mixed-replace\b/.test(contentType)) {
- return true;
- }
-
- if (contentType == "application/x-unknown-content-type" || /\b(?:xml|rss|javascript|json)\b/.test(contentType)) return false;
- var ms = MediaSniffer.mimeService;
- return fg.extensions.some(function(e) {
- try { return contentType == ms.getTypeFromExtensions(e); } catch(ex) { return false; }
- });
- }
- ,
- _willHandle: function(url, contentType) {
- if (!/^(http|https|ftp|sftp|rtsp|mms):/i.test(url) ) {
- if ((/^\s*javascript/i).test(url)) this.log("JavaScript url intercepted: "+url);
- return false;
- }
- return true;
- }
- ,
- extractPostData: function(channel, res) {
- res = res || {};
- res.postData = res.postStream = null;
- if (channel instanceof CI.nsIUploadChannel &&
- channel.uploadStream instanceof CI.nsISeekableStream) {
- this.log("Extracting post data...");
- var sis;
- try {
- res.postStream = channel.uploadStream;
- res.postStream.seek(0, 0);
- sis = CC['@mozilla.org/scriptableinputstream;1'].createInstance(CI.nsIScriptableInputStream);
- sis.init(res.postStream);
- var postData = sis.read(sis.available());
- res.postStream.seek(0, 0);
-
- // buffered persistent copy
- res.postStream = CC["@mozilla.org/io/string-input-stream;1"].createInstance(CI.nsIStringInputStream);
- res.postStream.setData(postData, postData.length);
- if (res.postStream instanceof CI.nsISeekableStream) res.postStream.seek(0, 0);
-
- // remove headers
- postData = postData.replace(/\s+$/,'').split(/[\r\n]+/)
- res.postData = postData[postData.length - 1];
- } catch(ex) {
- this.log(ex.message);
- } finally {
- if (sis) sis.close();
- }
- }
- return res;
- },
- /* nsIURIContentListener */
-
- canHandleContent: function(contentType, isContentPreferred, desiredContentType) {
- // dump("FG: canHandleContent "+contentType+")\n");
- return this._shouldIntercept(contentType);
- }
- ,
- lastRequest: null,
- doContent: function(contentType, isContentPreferred, channel, contentHandler) {
-
- channel.QueryInterface(CI.nsIChannel);
- const uri = channel.URI;
- // dump("FG: doContent " +contentType + " " + uri.spec + "\n");
- if (!this._willHandle(uri.spec, contentType)) {
- throw new Error("FlashGot not interested in " + contentType + " from " + uri.spec);
- }
-
- this.log("Intercepting download...");
-
- const pathParts=uri.path.split(/\//);
- var links = [ {
- href: channel.URI.spec,
- description: pathParts[pathParts.length-1],
- noRedir: true
- } ];
-
-
-
- if (channel instanceof CI.nsIHttpChannel) {
- links.referrer = channel.referrer && channel.referrer.spec || "";
- this.extractPostData(channel, links);
- }
-
- try {
- links.document = channel.notificationCallbacks.QueryInterface(
- CI.nsIInterfaceRequestor).getInterface(
- CI.nsIDOMWindow).document;
- links.browserWindow = DOM.getChromeWindow(links.document.defaultView.top);
- if (links.browserWindow.wrappedJSObject) links.browserWindow = links.browserWindow.wrappedJSObject;
- } catch(e) {
- this.log("Can't set referrer document for " + links[0].href + " from " + links.referrer);
- }
-
- var firstAttempt;
- if (contentHandler) {
- this.lastRequest = null;
- firstAttempt = true;
- this.forceAutoStart = false;
- } else {
- var requestLines = [ channel.requestMethod, links[0].href, links.referrer || "", links.postData || ""].join("\n\n");
- firstAttempt = this.lastRequest != requestLines;
- this.lastRequest = requestLines;
- }
-
- if (firstAttempt) {
- var self = this;
- fg.delayExec(function() {
- self.forceAutoStart = false;
- if(fg.download(links))
- self.log("...interception done!");
- }, 10);
- } else {
- // dump("Second attempt, skipping.\n");
- this.lastRequest = null;
- this.forceAutoStart = false;
- }
-
- if (!channel.isPending()) {
- try {
- channel.requestMethod = "HEAD";
- channel.loadFlags = CI.nsIChannel.LOAD_RETARGETED | CI.nsIChannel.LOAD_RETARGETED_DOCUMENT_URI | CI.nsICachingChannel.LOAD_ONLY_FROM_CACHE;
- } catch(e) {}
- }
- channel.cancel(NS_BINDING_ABORTED);
-
- this.log("Original request cancelled.");
-
- return true;
- },
- contentHandler: {
- onStartRequest: function(request, context) {
- throw "cancelled";
- },
- onStopRequest: function() {},
- onDataAvailable: function() {}
- }
- ,
- isPreferred: function(contentType, desiredContentType) {
- // dump("FG: isPreferred("+contentType+","+desiredContentType+")\n");
- return this._shouldIntercept(contentType);
- }
- ,
- onStartURIOpen: function(uri) {
- // dump("FG: onStartURIOpen "+ uri + (uri && uri.spec) + "\n");
- return false;
- }
- ,
- // http-on-modify-request Observer
- observe: function(channel, topic, data) {
- if (channel instanceof CI.nsIHttpChannel) {
-
- if (channel instanceof CI.nsIUploadChannel) {
- this.lastPost = channel;
- }
- if (this.forceAutoStart) {
- this.doContent("flashgot/forced", true, channel, null);
- return;
- }
-
-
- }
- }
- };